from __future__ import absolute_import, division

from gui.panda.base import *


class Heightfield(PNMImage):
    def __init__(self, map, detail):
        assert map is not None
        assert detail >= 0
        
        # Map dimensions need to be powers of 2
        assert math.log(map.width,  2) % 1 == 0
        assert math.log(map.height, 2) % 1 == 0
        
        self._map    = map
        self._detail = detail
        
        super(Heightfield, self).__init__(self.width, self.height)
        
        self.fill(0, 0, 0)

        for tile in self.map:
            if tile.x == self.map.width - 1:
                ddx = 2
            else:
                ddx = 1
            
            if tile.y == self.map.height - 1:
                ddy = 2
            else:
                ddy = 1
            
            if tile.is_water:
                coast = []
                
                for dx in [-1, 0, 1]:
                    for dy in [-1, 0, 1]:
                        if dx == dy ==0:
                            continue
                        
                        x = tile.in_direction(dx, dy)
                        
                        if x.is_in_bounds and not x.is_water:
                            coast.append((dx, dy))
            
            for dx in range(self.inner_nodes + ddx):
                for dy in range(self.inner_nodes + ddy):
                    x = tile.x * (self.inner_nodes + 1) + dx
                    y = tile.y * (self.inner_nodes + 1) + dy
                    
                    if tile.is_water:
                        east = west = north = south = 0
                        
                        if (-1, 0) in coast:
                            west  = max(1 - dx / self.inner_nodes, 0)
                        
                        if (+1, 0) in coast:
                            east  = max(dx / self.inner_nodes, 0)
                        
                        if (0, -1) in coast:
                            north = max(1 - dy / self.inner_nodes, 0)
                        
                        if (0, +1) in coast:
                            south = max(dy / self.inner_nodes, 0)
                        
                        if len(coast) > 0:
                            self.setXel(x, y, 0.1925 + 0.01 * max((west, east, north, south)))
                        else:
                            self.setXel(x, y, 0.19)
                    else:
                        self.setXel(x, y, 0.21 + random.random() * 0.0025)
    
    @property
    def map(self):
        return self._map
    
    @property
    def detail(self):
        return self._detail
    
    @property
    def inner_nodes(self):
        return 2 ** self.detail - 1
    
    @property
    def width(self):
        return self.map.width * (self.inner_nodes + 1) + 1
    
    @property
    def height(self):
        return self.map.height * (self.inner_nodes + 1) + 1
    
    @property
    def scale_x(self):
        return self.map.width / self.width
    
    @property
    def scale_y(self):
        return self.map.height / self.height
